package com.sense.cloud.common;

import com.alibaba.fastjson.JSONObject;
import com.sense.http.HttpConnectPoolInvoke;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 本类及 lib 目录下的 jar 包是 OpenAPI V2 的请求封装类，只用于 demo 示例, 不应用于生产环境中。
 *
 * Created by kanghl on 2017/11/1.
 */
public class API2Request {

    private String appUrl;
    private String appId;
    private String appSecret;

    public API2Request(String appUrl, String appId, String appSecret) {
        this.appUrl = appUrl;
        this.appId = appId;
        this.appSecret = appSecret;
    }

    /**
     * 发送请求接口
     * @param reqUrl         请求地址
     * @param reqDataJson    请求的 json 对象数据
     * @return
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     * @throws IOException
     * @throws URISyntaxException
     * @throws InvalidKeyException
     */
    public JSONObject send(String reqUrl,JSONObject reqDataJson) throws KeyManagementException, NoSuchAlgorithmException, IOException, URISyntaxException, InvalidKeyException {
        String result = buildRequest(reqUrl,reqDataJson);
        System.out.println("result:"+result);
        return JSONObject.parseObject(result);
    }

    /**
     * 请求构建、发送，获取返回数据
     * @param reqUrl
     * @param reqDataJson
     * @return
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     */
    private String buildRequest(String reqUrl,JSONObject reqDataJson) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
        Map<String,String> headers = new HashMap<>();
        //填充请求头
        headers.put("Content-type","application/json");
        headers.put("SenseAppID",this.appId);
        //取当前时间放置请求头中
        headers.put("SenseTimestamp",String.valueOf(System.currentTimeMillis()));
        //放置随机数
        headers.put("SenseNonce", UUID.randomUUID().toString());
        // 旋转请求数据签名
        headers.put("SenseSign",this.makeSignature(reqUrl,
                reqDataJson.toJSONString(),
                headers.get("SenseTimestamp"),
                headers.get("SenseNonce")));
        // 放置请求数据
        //发送请求，并返回请求结果
        return HttpConnectPoolInvoke.sendHttpPostBytesRequest(this.appUrl+reqUrl,reqDataJson.toJSONString().getBytes(),headers);
    }

    /**
     * 将请求数据进行签名处理(HmacSHA256)，服务端会验签
     * @param requrl    请求地址
     * @param reqbody   请求的body数据
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @return          签名结果的 base64
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    private String makeSignature(String requrl,String reqbody,String timestamp,String nonce) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {

        SecretKeySpec keySpec= new SecretKeySpec(this.appSecret.getBytes("UTF-8"),"HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(keySpec);
        byte[] resultBytes = mac.doFinal((timestamp+nonce+requrl+reqbody).getBytes("UTF-8"));
        // 将签名数据进行 base64 编码
        return Base64.encodeBase64String(resultBytes);

    }
}
